
const suspectProtoRx = /(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])/;
const suspectConstructorRx = /(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)/;


module.exports = function (source, reviver) {
  'use strict';
  const _options = {
    strict: false, // 不严格意味着不会为“重复键”生成语法错误
    protoAction: 'error',
    constructorAction: 'error',
  };
  if (typeof source != "string") return source;
  var at = 0, // 当前字符的索引
    ch = ' ', // 当前角色
    text = source, escapee = {
      '"': '"',
      '\\': '\\',
      '/': '/',
      b: '\b',
      f: '\f',
      n: '\n',
      r: '\r',
      t: '\t',
    },
    error = function (m) {
      // 出错时呼叫错误。
      throw {
        name: 'SyntaxError',
        message: m,
        at: at,
        text: text,
      };
    },
    next = function (c) {
      // 如果提供了c参数，请验证它是否与当前字符匹配。
      if (c && c !== ch) {
        error("Expected '" + c + "' instead of '" + ch + "'");
      }
      // 获得下一个字符。当没有更多的字符时，返回空字符串。
      ch = text.charAt(at++);
      // at++;
      return ch;
    },
    number = function () {
      // 解析数值。

      var number,
        string = '';

      if (ch === '-') {
        string = '-';
        next('-');
      }
      while (ch >= '0' && ch <= '9') {
        string += ch;
        next();
      }
      if (ch === '.') {
        string += '.';
        while (next() && ch >= '0' && ch <= '9') {
          string += ch;
        }
      }
      if (ch === 'e' || ch === 'E') {
        string += ch;
        next();
        if (ch === '-' || ch === '+') {
          string += ch;
          next();
        }
        while (ch >= '0' && ch <= '9') {
          string += ch;
          next();
        }
      }
      number = +string;
      if (!isFinite(number)) {
        error('Bad number');
      } else {
        //if (number > 9007199254740992 || number < -9007199254740992)

        return BigInt(number);
      }
    },
    string = function () {
      // 分析字符串值。

      var hex,
        i,
        string = '',
        uffff;

      // 解析字符串值时，必须查找 " and \  字符。

      if (ch === '"') {
        var startAt = at;
        while (next()) {
          if (ch === '"') {
            if (at - 1 > startAt) string += text.substring(startAt, at - 1);
            next();
            return string;
          }
          if (ch === '\\') {
            if (at - 1 > startAt) string += text.substring(startAt, at - 1);
            next();
            if (ch === 'u') {
              uffff = 0;
              for (i = 0; i < 4; i += 1) {
                hex = parseInt(next(), 16);
                if (!isFinite(hex)) {
                  break;
                }
                uffff = uffff * 16 + hex;
              }
              string += String.fromCharCode(uffff);
            } else if (typeof escapee[ch] === 'string') {
              string += escapee[ch];
            } else {
              break;
            }
            startAt = at;
          }
        }
      }
      error('Bad string');
    },
    white = function () {
      // 跳过空白。
      while (ch && ch <= ' ') {
        next();
      }
    },
    word = function () {
      // true, false, or null.

      switch (ch) {
        case 't':
          next('t');
          next('r');
          next('u');
          next('e');
          return true;
        case 'f':
          next('f');
          next('a');
          next('l');
          next('s');
          next('e');
          return false;
        case 'n':
          next('n');
          next('u');
          next('l');
          next('l');
          return null;
      }
      error("Unexpected '" + ch + "'");
    },
    value = function () {
      // 解析JSON值。它可以是 an object, an array, a string, a number or a word.

      white();
      switch (ch) {
        case '{':
          return object();
        case '[':
          return array();
        case '"':
          return string();
        case '-':
          return number();
        default:
          return ch >= '0' && ch <= '9' ? number() : word();
      }
    },
    array = function () {
      // 分析数组值。
      const array = [];
      if (ch === '[') {
        next('[');
        white();
        if (ch === ']') {
          next(']');
          return array; // empty array
        }
        while (ch) {
          array.push(value());
          white();
          if (ch === ']') {
            next(']');
            return array;
          }
          next(',');
          white();
        }
      }
      error('Bad array');
    },
    object = function () {
      // 分析对象值。
      let key;
      const obj = {};
      if (ch === '{') {
        next('{');
        white();
        if (ch === '}') {
          next('}');
          return obj; // 空对象
        }
        while (ch) {
          key = string();
          white();
          next(':');
          if (
            _options.strict === true &&
            Object.hasOwnProperty.call(obj, key)
          ) {
            error('Duplicate key "' + key + '"');
          }

          if (suspectProtoRx.test(key) === true) {
            if (_options.protoAction === 'error') {
              error('Object contains forbidden prototype property');
            } else if (_options.protoAction === 'ignore') {
              value();
            } else {
              obj[key] = value();
            }
          } else if (suspectConstructorRx.test(key) === true) {
            if (_options.constructorAction === 'error') {
              error('Object contains forbidden constructor property');
            } else if (_options.constructorAction === 'ignore') {
              value();
            } else {
              obj[key] = value();
            }
          } else {
            obj[key] = value();
          }

          white();
          if (ch === '}') {
            next('}');
            return obj;
          }
          next(',');
          white();
        }
      }
      error('Bad object');
    };


  // 返回json解析函数。它将访问上述所有函数和变量。
  const result = value();
  white();
  if (ch) {
    error('Syntax error');
  }
  // 如果有一个恢复函数，我们递归地遍历新结构，
  // 将每个 name/value 传递给reviver函数以进行可能的转换，
  // 从将结果保存在空键中的临时根对象开始。 如果没有恢复函数，我们只返回结果。
  function recursion(data, key) {
    let v, value = data[key];
    if (value && typeof value === 'object') {
      Object.keys(value).forEach(function (k) {
        v = recursion(value, k);
        if (v !== undefined) {
          value[k] = v;
        } else {
          delete value[k];
        }
      });
    }
    return reviver.call(data, key, value);
  }

  return typeof reviver === 'function'
    ? recursion({ '': result }, '')
    : result;
};
